using System;
using System.Collections.Generic;
using System.Linq;
using IssueIT.Core.Domain.Exceptions;

namespace IssueIT.Core.Domain.Model
{
	public class Issue : IEntity
	{
		private readonly IList<Post> _postList = new List<Post>();
		private readonly IList<PointInTime> _milestones = new List<PointInTime>();
		private readonly TagList _tags = new TagList();

		public Issue(Post post)
		{
			_postList.Add(post);
		}

		private Post FirstPost
		{
			get
			{
				return _postList.First();
			}
		}

		private Post LatestPost
		{
			get
			{
				return _postList.Last();
			}
		}

		public Guid Id { get; set; }

		/// <summary>
		/// numbered consecutively within a project, 1..2..3.etc.
		/// </summary>
		public int Number { get; set; }

		public string Title
		{
			get
			{
				return LatestPost.Title;
			}
		}

		public Guid Revision
		{
			get
			{
				return LatestPost.Id;
			}
		}

		public User CreatedBy
		{
			get
			{
				return FirstPost.CreatedBy;
			}
		}

		public DateTime CreatedAt
		{
			get
			{
				return FirstPost.CreatedAt;
			}
		}

		public virtual Status Status
		{
			get
			{
				return _postList.Last().Status;
			}
		}

		public IEnumerable<Post> PostList(User visibleTo)
		{
			return _postList.Where(p => p.IsVisibleTo(visibleTo));
		}

		public IEnumerable<PointInTime> Milestones
		{
			get
			{
				return _milestones;
			}
		}

		public TagList Tags
		{
			get
			{
				return _tags;
			}
		}

		//newIssuePost command newIssuePostRequest
		public void AddPost(Post newPost, Guid lastRevision)
		{
			if( !Revision.Equals(lastRevision) )
			{
				throw new IssueHasBeenUpdatedException(newPost);
			}

			_postList.Add(newPost);
		}

		public void AddMilestone(PointInTime newPointInTime)
		{
			_milestones.Add(newPointInTime);
		}

		public void DeleteMilestone(Guid milestoneId)
		{
			var toDelete = _milestones.FirstOrDefault(m => m.Id==milestoneId);
			if( toDelete==null )
			{
				throw new InvalidOperationException("Unknown milestone: " + milestoneId);
			}

			toDelete.Delete();
		}

		public bool DeleteTag(string tagText)
		{
			return _tags.Remove(tagText);
		}
	}
}